package cz.cuni.mff.ufal.volk.patterns.test;

import static org.junit.Assert.*;

import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import org.junit.BeforeClass;
import org.junit.Test;

import alice.tuprolog.InvalidTheoryException;

import cz.cuni.mff.ufal.volk.patterns.LanguageDescription;
import cz.cuni.mff.ufal.volk.patterns.Pattern;

public class PatternTest1 {

	@BeforeClass
	public static void prepare() throws IOException {
		FileInputStream in = new FileInputStream("pl/cz_lang.pl");
		try {
			czechDesc = new LanguageDescription(in);
		} finally {
			in.close();
		}
	}

	private static LanguageDescription czechDesc;

	@Test
	public void simple1() throws FileNotFoundException, IOException,
	    InvalidTheoryException {
		LanguageDescription desc = new LanguageDescription(
		    new ByteArrayInputStream(new byte[0]));
		Pattern pat = new Pattern(desc,
		    "zażółć gęślą jaźń # xat(x) :- (1 + 2) is 3.");
		String out = pat.evaluate();
		assertEquals("zażółć gęślą jaźń ", out);
	}

	@Test
	public void simpleVar0() throws IOException, InvalidTheoryException {
		FileInputStream in = new FileInputStream("pl/cz_lang.pl");
		try {
			LanguageDescription desc = new LanguageDescription(in);
			Pattern pat = new Pattern(desc, "Ty jsi =b= holka.# cond([b-->[case == nom, num == sg, gen == fem]]).");
			String out = pat.evaluate("b", "@beautiful");
			assertEquals("Ty jsi krásná holka.", out);
		} finally {
			in.close();
		}
	}

	@Test
	public void simpleVar1() throws IOException, InvalidTheoryException {
		Pattern pat = new Pattern(czechDesc, "Ty jsi =b= holka.# cond([b-->[gen == fem]]).");
		String out = pat.evaluate("b", "@beautiful");
		assertEquals("Ty jsi krásná holka.", out);
	}

	@Test
	public void simpleVar2() throws IOException, InvalidTheoryException {
		Pattern pat = new Pattern(czechDesc, "Ty jsi =b= holka.# cond([b-->[gen == fem]]).");
		String out = pat.evaluate("b", "@beautiful");
		assertEquals("Ty jsi krásná holka.", out);
	}

	@Test
	public void coord1() throws IOException, InvalidTheoryException {
		Pattern pat = new Pattern(czechDesc, "Hele, =adj= =noun= =verb=.#" + "cond(["
		    + "adj-->[case==nom, num==sg, gen == G], "
		    + "noun --> [case==nom, num==sg, gen==G], "
		    + "verb --> [person==third, num==sg]" +
		  "]).");
		String out = pat.evaluate("adj", "@beautiful", "noun", "@girl", "verb", "@eat");
		assertEquals("Hele, krásná holka jí.", out);
	}

	@Test
	public void coord2() throws IOException, InvalidTheoryException {
		Pattern pat = new Pattern(czechDesc, "Hele\\=, =adj= =noun= =verb=.#" +
				"cond(["
		    + "adj-->[case==C, num==N, gen == G], "
		    + "noun --> [case==C, num==N, gen==G], "
		    + "verb --> [person==third, num==N]" +
		  "]) :- N=sg, C=nom.");
		String out = pat.evaluate("adj", "@beautiful", "noun", "@girl", "verb", "@eat");
		assertEquals("Hele=, krásná holka jí.", out);
	}

	@Test
	public void coord3() throws IOException, InvalidTheoryException {
		Pattern pat = new Pattern(czechDesc, "Dávám to =adj= =noun=.# cond([adj --> [case==dat, num==N, gen==G], noun --> [case==dat, num==N, gen==G]]).");
		String out = pat.evaluate("noun", "@girl", "adj", "@beautiful");
		assertEquals("Dávám to krásné holce.", out);
	}

	@Test
	public void ending1() throws IOException, InvalidTheoryException {
		Pattern pat = new Pattern(czechDesc, "Toto je krásn=ending= =noun=.#" +
				"cond([ending:='á', noun-->[case==nom, num==sg, gen==fem]]). " +
				"cond([ending:='ý', noun-->[case==nom, num==sg, gen==masc]]). " +
				"cond([ending:='é', noun-->[case==nom, num==sg, gen==neut]]).");
		String out = pat.evaluate("noun", "@hedgehog");
		assertEquals("Toto je krásný ježek.", out);
	}

	@Test
	public void facebook1() throws IOException, InvalidTheoryException {
		Pattern pat = new Pattern(czechDesc, "=n= =yf= se to líbí.#" +
				"cond([n := 1, yf := 'tvému příteli']). " +
				"cond([n := _, yf := 'tvým přátelům']). ");
		String out = pat.evaluate("n", "1");
		assertEquals("1 tvému příteli se to líbí.", out);
	}

	@Test
	public void facebook2() throws InvalidTheoryException {
		Pattern pat = new Pattern(czechDesc, "=n= =yf= se to líbí.#" +
				"cond([n := 1, yf := 'tvému příteli']). " +
				"cond([n := _, yf := 'tvým přátelům']). ");
		String out = pat.evaluate("n", "15");
		assertEquals("15 tvým přátelům se to líbí.", out);
	}

	@Test
	public void escapeSequence() throws InvalidTheoryException {
		Pattern pat = new Pattern(czechDesc, "Теď si vyzkoušíme vzorec, který obsahuje hodně ošklivých znaků: \\=\\\\=x=\\##cond(x-->[case==nom,num==sg]).");
		String out = pat.evaluate("x", "@girl");
		assertEquals("Теď si vyzkoušíme vzorec, který obsahuje hodně ošklivých znaků: =\\holka#", out);
	}

	@Test
	public void var1() throws InvalidTheoryException {
		Pattern pat = new Pattern(czechDesc, "=name= =verb=, že...#" +
				"cond([verb := 'napsal', gen := 'm']). " +
				"cond([verb := 'napsala', gen := 'f']).");
		String out = pat.evaluate("name", "Magda", "gen", "f");
		assertEquals("Magda napsala, že...", out);
	}

	@Test
	public void var2() throws InvalidTheoryException {
		Pattern pat = new Pattern(czechDesc, "=name= napsal=ending=, že...#" +
				"cond([ending := '', gen := 'm']). " +
				"cond([ending := 'a', gen := 'f']).");
		String out = pat.evaluate("name", "Ježek", "gen", "m");
		assertEquals("Ježek napsal, že...", out);
	}

	@Test
	public void var3s() throws InvalidTheoryException {
		Pattern pat = new Pattern(czechDesc, "=pointer= =noun= jí.#" +
				"cond([pointer := 'Tato', noun := 'holka', noun --> [case == nom]]). " +
				"cond([pointer := 'Tento', noun := 'kluk', noun --> [case == nom]]). ");
		String out = pat.evaluate("noun", "@boy");
		assertEquals("Tento kluk jí.", out);
	}

	@Test
	public void num1() {
		Pattern pat = new Pattern(LanguageDescription.EMPTY, "Našel jsem =c= nov=ae= zpráv=ne=.#" +
				"cond([count := 1, c := 'jednu', ae := 'ou', ne := 'u']). " +
				"cond([count := 2, c := 'dvě', ae := 'é', ne := 'y']). " +
				"cond([count := 3, c := 'tři', ae := 'é', ne := 'y']). " +
				"cond([count := 4, c := 'čtyři', ae := 'é', ne := 'y']). " +
				"cond([count := C, c := C, ae := 'ých', ne := '']).");
		String out = pat.evaluate("count", "4");
		assertEquals("Našel jsem čtyři nové zprávy.", out);
	}

	@Test
	public void num2() {
		Pattern pat = new Pattern(LanguageDescription.EMPTY, "Našel jsem =c= nov=ae= zpráv=ne=.#" +
				"cond([count := 1, c := 'jednu', ae := 'ou', ne := 'u']). " +
				"cond([count := 2, c := 'dvě', ae := 'é', ne := 'y']). " +
				"cond([count := 3, c := 'tři', ae := 'é', ne := 'y']). " +
				"cond([count := 4, c := 'čtyři', ae := 'é', ne := 'y']). " +
				"cond([count := C, c := C, ae := 'ých', ne := '']).");
		String out = pat.evaluate("count", "5");
		assertEquals("Našel jsem 5 nových zpráv.", out);
	}

	@Test
	public void simpleEvaluation1() throws InvalidTheoryException {
		Pattern pat = new Pattern(czechDesc, "=var=# cond([]).");
		String out = pat.evaluate("var", "a");
		assertEquals("a", out);
	}

	@Test
	public void invalidEvaluation() throws InvalidTheoryException {
		Pattern pat = new Pattern(czechDesc, "=var=# cond([]).");
		String out = pat.evaluate("var", "a", "var", "b");
		assertEquals("?null", out);
	}

	@Test
	public void invalidTheory() throws InvalidTheoryException {

	}

}
